<?php

namespace Tasker\Authentication;

use \Nette\Security as NS;

class Authenticator implements NS\IAuthenticator
{
	/**
	 * @var \NotORM
	 */
	protected $connection;
	/**
	 * @var string
	 */
	protected $staticSalt;
	/**
	 * @var string
	 */
	protected $algorithm = "sha512";
	
	public function __construct(\NotORM $connection, array $options)
	{
		$this->connection = $connection;
		if(!isset($options['salt']))
			throw new \Nette\InvalidArgumentException("Options must contain 'salt' key");
		$this->staticSalt = $options['salt'];
		
		if(isset($options['algorithm']))
			$this->algorithm = $options['algorithm'];
	}
	
	/**
	 * Performs an authentication
	 * @param  array
	 * @return Nette\Security\Identity
	 * @throws Nette\Security\AuthenticationException
	 */
	public function authenticate(array $credentials)
	{
		$user = $this->checkUser($credentials);
		
		$roles = array($user->user_role['role']);
		foreach ($this->connection->project_role() as $role)
		{
			$roles[] = $role['role'];
		}


		unset($user['password']);
		return new NS\Identity($user['id'], $roles, $user);
	}

	
	public function checkUser(array $credentials)
	{
		list($username, $password) = $credentials;
		$user = $this->connection->user('login', $username)->where('active','yes')->fetch();

		if (!$user)
		{
			throw new NS\AuthenticationException("Uživatel '$username' nebyl nalezen.", self::IDENTITY_NOT_FOUND);
		}
		
		list($db_password, $db_salt) = explode(":", $user['password']);
		
		if ($db_password !== $this->calculateHash($password, $db_salt))
		{
			throw new NS\AuthenticationException("Nesprávné heslo.", self::INVALID_CREDENTIAL);
		}

		return $user;
	}


	/**
	 * Computes salted password hash.
	 * @param  string
	 * @return string
	 */
	public function calculateHash($password, $dynamicSalt)
	{
		return sha1(hash($this->algorithm, $password 
				. str_repeat($this->staticSalt, 10)) . $dynamicSalt);
	}

}

